<?php

namespace App\Http\Controllers\Api\Plane;

use App\Events\Plane\PlaneTicketQueryEvent;
use App\Http\Controllers\Controller;
use App\Http\Requests\Plane\Rules\RuleQueryRequest;
use App\Models\User\User;
use App\Trip\Enums\Plane\PlaneProviders;
use App\Trip\Plane\Api\FlightQuery;
use App\Trip\Plane\Factories\PlaneQueryFactory;
use App\Trip\Plane\Interfaces\PlaneQueryInterface;
use App\Trip\Plane\MixedPlaneQueryResult;
use App\Trip\Plane\Requests\BeforeBookRequest;
use App\Trip\Plane\Requests\PriceCalendarRequest;
use App\Trip\Plane\Requests\RulesRequest;
use App\Trip\Plane\Requests\TicketPriceRequest;
use App\Trip\Plane\Requests\TicketQueryRequest;
use App\Trip\Plane\Resp\RulesResponse;
use App\Trip\Plane\Rules\SystemRules;
use App\Trip\Plane\Variflight\FlightComfort;
use App\Trip\Plane\Variflight\VariflightRequest;
use Carbon\Carbon;
use Carbon\Exceptions\InvalidFormatException;
use Exception;
use GuzzleHttp\Exception\GuzzleException;
use Illuminate\Http\Request;

class PlaneController extends Controller
{

    private ?User               $user;
    private PlaneQueryInterface $planeQuery;

    public function __construct()
    {
        // 制造book 51 工厂 目前用于 规则和日历
        $this->planeQuery = (new PlaneQueryFactory())->findOneByProvider(PlaneProviders::BOOK51);
        $this->user       = auth()->user() ?: null;
    }


    /**
     * @throws InvalidFormatException
     * @throws Exception
     */
    public function ticket_query(Request $request)
    {
        $ticket_request = new TicketQueryRequest($request);
        // mixed
        $queryRes        = new MixedPlaneQueryResult($ticket_request);
        $query           = new FlightQuery($queryRes, $ticket_request);
        $res             = $query->getResult();
        $res['calendar'] = $this->planeQuery->price_calendar(new PriceCalendarRequest([
            'trip_date' => $ticket_request->getTripDate(),
            'from'      => $ticket_request->getFrom(),
            'to'        => $ticket_request->getTo(),
        ]));
        event(new PlaneTicketQueryEvent([
            'from'       => $ticket_request->getFrom()->toArray(),
            'to'         => $ticket_request->getTo()->toArray(),
            'user'       => $this->user,
            'updated_at' => Carbon::now()->toDateTimeString(),
        ]));
        return $this->success('', $res);
    }

    /**
     * 低价日历
     */
    public function price_calendar(Request $request)
    {
        $calendar_request = new PriceCalendarRequest($request);
        $response         = $this->planeQuery->price_calendar($calendar_request);
        return $this->success('', $response->toArray());
    }

    /**
     * 航班价格
     * @throws InvalidFormatException
     * @throws Exception
     */
    public function ticket_price(Request $request)
    {
        $price_request = new TicketPriceRequest($request);
        $planeQuery    = $price_request->getProvider()->getPlaneQueryStrategy();
        $response      = $planeQuery->ticket_price($price_request);
        return $this->success('', $response->getInfo());
    }

    /**
     * @throws GuzzleException
     */
    public function comfort(Request $request)
    {
        $req = new VariflightRequest($request);
        $v   = new FlightComfort();
        $res = $v->queryByFlightNo($req);
        return $this->success('', $res->findOneByFlightNo($req->getFlightNo()));
    }

    /**
     * @throws InvalidFormatException
     */
    public function before_book(Request $request)
    {
        $before_request = new BeforeBookRequest($request);
        $planeOrder     = $before_request->getProvider()->getPlaneOrderStrategy();
        $res            = $planeOrder->before_book($before_request);
        return $this->success('', $res->toArray());
    }

    /**
     * @throws Exception
     */
    public function rules(RuleQueryRequest $request)
    {
        // 使用系统规则
        $systemRules = new SystemRules(new RulesRequest($request));
        $res         = new RulesResponse($systemRules->toArray());
//        $res = $this->planeQuery->rules(new RulesRequest($request));
        return $this->success('', $res->toArray());

    }
}
